<?php


namespace app\common\logic;

use think\facade\Db;
use think\Cache;
use think\Image;
use think\Validate;
use app\common\model\WxNews;
use app\common\model\WxReply;
use app\common\model\WxTplMsg;
use app\common\model\WxKeyword;
use app\common\model\WxMaterial;
use app\common\logic\wechat\WechatUtil;

/**
 * 微信公众号的业务逻辑类
 */
class WechatLogic
{
    static private $wx_user = null;
    static private $wechat_obj;

    public function __construct($config = null)
    {
        if (!self::$wx_user) {
            if ($config === null) {
                $config = Db::name('wx_set')->find();
            } 
            self::$wx_user = $config;
            self::$wechat_obj = new WechatUtil(self::$wx_user);
        }
    }

    /**
     * 处理接收推送消息
     */
    public function handleMessage()
    {
        self::$wechat_obj->registerMsgEvent(WechatUtil::EVENT_TEXT, function ($msg) {
            $this->handleTextMsg($msg);
        });

        self::$wechat_obj->registerMsgEvent(WechatUtil::EVENT_CLICK, function ($msg) {
            $this->handleClickEvent($msg);
        });

        self::$wechat_obj->registerMsgEvent(WechatUtil::EVENT_SUBSCRIBE, function ($msg) {
            $this->handleSubscribeEvent($msg);
        });

        self::$wechat_obj->handleMsgEvent();
    }

    /**
     * 处理关注事件
     * @param array $msg
     * @return array
     */
    private function handleSubscribeEvent($msg)
    {
        $openid = $msg['FromUserName'];
        if (!$openid) {
            exit("openid无效");
        }

        if ($msg['MsgType'] != 'event' || $msg['Event'] != 'subscribe') {
            exit("不是关注事件");
        }

        if (! Db::name('oauth_users')->where('openid', $openid)->find()) {
            if (false === ($wxdata = self::$wechat_obj->getFanInfo($openid))) {
                exit(self::$wechat_obj->getError());
            }
            $userData = [
                'head_pic'  => $wxdata['headimgurl'],
                'nickname'  => $wxdata['nickname'] ?: '微信用户',
                'sex'       => $wxdata['sex'] ?: 0,
                'reg_time'  => time(),
                'password'  => '',
                'is_distribut' => 1,
            ];

            // 由场景值获取分销一级id
            if (!empty($msg['EventKey'])) {
                $userData['first_leader'] = substr($msg['EventKey'], strlen('qrscene_'));
                if ($userData['first_leader']) {
                    $first_leader = Db::name('users')->where('user_id', $userData['first_leader'])->find();
                    if ($first_leader) {
                        $userData['second_leader'] = $first_leader['first_leader']; //  第一级推荐人
                        $userData['third_leader'] = $first_leader['second_leader']; // 第二级推荐人
                        //他上线分销的下线人数要加1
                        Db::name('users')->where('user_id', $userData['first_leader'])->setInc('underling_number');
                        Db::name('users')->where('user_id', $userData['second_leader'])->setInc('underling_number');
                        Db::name('users')->where('user_id', $userData['third_leader'])->setInc('underling_number');
                    }
                } else {
                    $userData['first_leader'] = 0;
                }
            }
            $is_bind_account = tpCache('basic.is_bind_account');
            if($is_bind_account && $userData['first_leader']){
                //如果是绑定账号, 把first_leader保存到cookie
                setcookie('user_id', $userData['first_leader'] ,null,'/');
            }else{
                $user_id = Db::name('users')->insertGetId($userData);
                Db::name('oauth_users')->insert([
                'user_id' => $user_id,
                'openid' => $openid,
                'unionid' => isset($wxdata['unionid']) ? $wxdata['unionid'] : '',
                'oauth' => 'weixin',
                'oauth_child' => 'mp',
                ]);
            } 
        }

        $this->replySubscribe($msg['ToUserName'], $openid);
    }

    /**
     * 关注时回复消息
     */
    private function replySubscribe($from, $to)
    {
        $result_str = $this->createReplyMsg($from, $to, WxReply::TYPE_FOLLOW);
        if ( ! $result_str) {
            //没有设置关注回复，则默认回复如下：
            $store_name = tpCache("shop_info.store_name");
            $result_str = self::$wechat_obj->createReplyMsgOfText($from, $to, "欢迎来到 $store_name !\n商城入口：".SITE_URL.'/mobile');
        }

        exit($result_str);
    }

    /**
     * 创建回复消息
     * @param $from string 发送方
     * @param $to string 被发送方
     * @param $type string WxReply的类型
     * @param array $data 附加数据
     * @return string
     */
    private function createReplyMsg($from, $to, $type, $data = [])
    {
        if ($type != WxReply::TYPE_KEYWORD) {
            $reply = WxReply::get(['type' => $type]);
        } else {
            $wx_keyword = WxKeyword::get(['keyword' => $data['keyword'], 'type' => WxKeyword::TYPE_AUTO_REPLY], 'wxReply');
            $wx_keyword && $reply = $wx_keyword->wx_reply;
        }

        if (empty($reply)) {
            return '';
        }

        $resultStr = '';
        if ($reply->msg_type == WxReply::MSG_TEXT && $reply['data']) {
            $resultStr = self::$wechat_obj->createReplyMsgOfText($from, $to, $reply['data']);
        } elseif ($reply->msg_type == WxReply::MSG_NEWS) {
            $resultStr = $this->createNewsReplyMsg($from, $to, $reply->material_id);
        } else {
            //扩展其他类型，如image，voice等
        }

        return $resultStr;
    }

    /**
     * 处理点击事件
     * @param array $msg
     */
    private function handleClickEvent($msg)
    {
        $from = $msg['ToUserName'];
        $to = $msg['FromUserName'];
        $eventKey = $msg['EventKey'];
        $distribut = tpCache('distribut');

        // 分销二维码图片
        if ($eventKey === $distribut['qrcode_menu_word']) {
            $this->replyMyQrcode($msg);
        }

        // 关键字自动回复
        $this->replyKeyword($from, $to, $eventKey);
    }

    /**
     * 回复我的二维码
     */
    private function replyMyQrcode($msg)
    {
        $fromUsername = $msg['FromUserName'];
        $toUsername   = $msg['ToUserName'];
        $wechatObj = self::$wechat_obj;

        $user = Db::name('oauth_users')->alias('o')->join('__USERS__ u', 'u.user_id=o.user_id')
            ->field('u.*')->where('o.openid', $fromUsername)->find();
        if (!$user) {
            $content = '请进入商城: '.SITE_URL.' , 再获取二维码哦';
            $reply = $wechatObj->createReplyMsgOfText($toUsername, $fromUsername, $content);
            exit($reply);
        }

        //获取缓存的图片id
        $distribut = tpCache('distribut');
        $mediaId = $this->getCacheQrcodeMedia($user['user_id'], $user['head_pic'], $distribut['qr_big_back']);
        if (!$mediaId) {
            $mediaId = $this->createQrcodeMedia($msg, $user['user_id'], $user['head_pic'], $distribut['qr_big_back']);
        }

        //回复图片消息
        $reply = $wechatObj->createReplyMsgOfImage($toUsername, $fromUsername, $mediaId);
        exit($reply);
    }

    private function createQrcodeMedia($msg, $userId, $headPic, $qrBackImg)
    {
        $wechatObj = self::$wechat_obj;

        //创建二维码关注url
        $qrCode = $wechatObj->createTempQrcode(2592000, $userId);
        if (!(is_array($qrCode) && $qrCode['url'])) {
            $this->replyError($msg, '创建二维码失败');
        }

        //创建分销二维码图片
        empty($headPic) && $headPic = '/public/images/icon_goods_thumb_empty_300.png'; //没有头像用默认图片
        $shareImg = $this->createShareQrCode('.'.$qrBackImg, $qrCode['url'], $headPic);
        if (!$shareImg) {
            $this->replyError($msg, '生成图片失败');
        }

        //上传二维码图片
        if (!($mediaInfo = $wechatObj->uploadTempMaterial($shareImg, 'image'))) {
            @unlink($shareImg);
            $this->replyError($msg, '上传图片失败');
        }
        @unlink($shareImg);

        $this->setCacheQrcodeMedia($userId, $headPic, $qrBackImg, $mediaInfo);

        return $mediaInfo['media_id'];
    }

    private function getCacheQrcodeMedia($userId, $headPic, $qrBackImg)
    {
        $symbol = md5("{$headPic}:{$qrBackImg}");
        $mediaIdCache = "distributQrCode:{$userId}:{$symbol}";
        $config = cache($mediaIdCache);
        if (!$config) {
            return false;
        }

        //$config = json_decode($config);
        //有效期3天（259200s）,提前5小时(18000s)过期
        if (!(is_array($config) && $config['media_id'] && ($config['created_at'] + 259200 - 18000) > time())) {
            return false;
        }

        return $config['media_id'];
    }

    private function setCacheQrcodeMedia($userId, $headPic, $qrBackImg, $mediaInfo)
    {
        $symbol = md5("{$headPic}:{$qrBackImg}");
        $mediaIdCache = "distributQrCode:{$userId}:{$symbol}";
        cache($mediaIdCache, $mediaInfo);
    }

    /**
     * 处理点击推送事件
     * @param array $msg
     */
    private function handleTextMsg($msg)
    {
        $from = $msg['ToUserName'];
        $to = $msg['FromUserName'];
        $keyword = trim($msg['Content']);

        //分销二维码图片
        $distribut = tpCache('distribut');
        if ($distribut['qrcode_input_word'] === $keyword) {
            $this->replyMyQrcode($msg);
        }

        // 关键字自动回复
        $this->replyKeyword($from, $to, $keyword);
    }

    /**
     * 关键字自动回复
     * @param $from
     * @param $to
     * @param $keyword
     */
    private function replyKeyword($from, $to, $keyword)
    {
        if (!$keyword) {
            $this->replyDefault($from, $to);
        }

        $resultStr = $this->createReplyMsg($from, $to, WxReply::TYPE_KEYWORD, ['keyword' => $keyword]);
        if ($resultStr) {
            exit($resultStr);
        } else {
            $this->replyDefault($from, $to);
        }
    }

    /**
     * 创建图文回复消息
     */
    private function createNewsReplyMsg($fromUser, $toUser, $material_id)
    {
        $material = WxMaterial::get(['id' => $material_id, 'type' => WxMaterial::TYPE_NEWS], 'wxNews');
        if (!$material || !$material->wx_news) {
            return '';
        }

        $articles = [];
        foreach ($material->wx_news as $news) {
            $articles[] = [
                'title'       => $news->title,
                'description' => $news->digest ?: $news->content_digest,
                'picurl'      => SITE_URL . $news->thumb_url,
                'url'         => SITE_URL . url('/mobile/article/news', ['id' => $news->id])
            ];
        }

        return self::$wechat_obj->createReplyMsgOfNews($fromUser, $toUser, $articles);
    }

    /**
     * 默认回复
     * @param array $msg
     */
    private function replyDefault($from, $to)
    {
        $resultStr = $this->createReplyMsg($from, $to, WxReply::TYPE_DEFAULT);
        if ( ! $resultStr) {
            //没有设置默认回复，则默认回复如下：
            $store_name = tpCache("shop_info.store_name");
            $resultStr = self::$wechat_obj->createReplyMsgOfText($from, $to, "欢迎来到 $store_name !");
        }

        exit($resultStr);
    }

    /**
     * 错误回复
     */
    private function replyError($msg, $extraMsg = '')
    {
        $fromUsername = $msg['FromUserName'];
        $toUsername   = $msg['ToUserName'];
        $wechatObj = self::$wechat_obj;

        if ($wechatObj->isDedug()) {
            $content = '错误信息：';
            $content .= $wechatObj->getError() ?: '';
            $content .= $extraMsg ?: '';
        } elseif ($extraMsg) {
            $content = '系统信息：'.$extraMsg;
        } else {
            $content = '系统正在处理...';
        }

        $resultStr = $wechatObj->createReplyMsgOfText($toUsername, $fromUsername, $content);
        exit($resultStr);
    }

    /**
     * 创建分享二维码图片
     * @param string $backImg 背景大图片
     * @param string $qrText  二维码文本:关注入口
     * @param string $headPic 头像路径
     * @return string 图片路径
     */
    private function createShareQrCode($backImg, $qrText, $headPic)
    {
        if (!is_file($backImg) || !$headPic || !$qrText) {
            return false;
        }

        vendor('phpqrcode.phpqrcode');
        vendor('topthink.think-image.src.Image');

        $qr_code_path = UPLOAD_PATH.'qr_code/';
        !file_exists($qr_code_path) && mkdir($qr_code_path, 0777, true);

        /* 生成二维码 */
        $qr_code_file = $qr_code_path.time().rand(1, 10000).'.png';
        \QRcode::png($qrText, $qr_code_file, QR_ECLEVEL_M);

        $QR = Image::open($qr_code_file);
        $QR_width = $QR->width();
        //$QR_height = $QR->height();

        /* 添加背景图 */
        if ($backImg && is_file($backImg)) {
            $back =Image::open($backImg);
            $backWidth = $back->width();
            $backHeight = $back->height();

            //生成的图片大小以540*960为准
            if ($backWidth <= $backHeight) {
                $refWidth = 540;
                $refHeight = 960;
                if (($backWidth / $backHeight) > ($refWidth / $refHeight)) {
                    $backRatio = $refWidth / $backWidth;
                    $backWidth = $refWidth;
                    $backHeight = $backHeight * $backRatio;
                } else {
                    $backRatio = $refHeight / $backHeight;
                    $backHeight = $refHeight;
                    $backWidth = $backWidth * $backRatio;
                }
            } else {
                $refWidth = 960;
                $refHeight = 540;
                if (($backWidth / $backHeight) > ($refWidth / $refHeight)) {
                    $backRatio = $refHeight / $backHeight;
                    $backHeight = $refHeight;
                    $backWidth = $backWidth * $backRatio;
                } else {
                    $backRatio = $refWidth / $backWidth;
                    $backWidth = $refWidth;
                    $backHeight = $backHeight * $backRatio;
                }
            }

            $shortSize = $backWidth > $backHeight ? $backHeight : $backWidth;
            $QR_width = $shortSize / 2;
            $QR_height = $QR_width;
            $QR->thumb($QR_width, $QR_height, \think\Image::THUMB_CENTER)->save($qr_code_file, null, 100);
            $back->thumb($backWidth, $backHeight, \think\Image::THUMB_CENTER)
                ->water($qr_code_file, \think\Image::WATER_CENTER, 90)->save($qr_code_file, null, 100);
            $QR = $back;
        }

        /* 添加头像 */
        if ($headPic) {
            //如果是网络头像
            if (strpos($headPic, 'http') === 0) {
                //下载头像
                $ch = curl_init();
                curl_setopt($ch,CURLOPT_URL, $headPic);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                $file_content = curl_exec($ch);
                curl_close($ch);
                //保存头像
                if ($file_content) {
                    $head_pic_path = $qr_code_path.time().rand(1, 10000).'.png';
                    file_put_contents($head_pic_path, $file_content);
                    $headPic = $head_pic_path;
                }
            }
            //如果是本地头像
            if (file_exists($headPic)) {
                $logo = Image::open($headPic);
                $logo_width = $logo->height();
                $logo_height = $logo->width();
                $logo_qr_width = $QR_width / 5;
                $scale = $logo_width / $logo_qr_width;
                $logo_qr_height = $logo_height / $scale;
                $logo_file = $qr_code_path.time().rand(1, 10000);
                $logo->thumb($logo_qr_width, $logo_qr_height)->save($logo_file, null, 100);
                $QR = $QR->water($logo_file, \think\Image::WATER_CENTER);
                unlink($logo_file);
            }
            if (!empty($head_pic_path)) {
                unlink($head_pic_path);
            }
        }

        //加上有效时间
        $valid_date = date('Y.m.d', strtotime('+30 days'));
        $QR->text('有效时间 '.$valid_date, "./vendor/topthink/think-captcha/assets/zhttfs/1.ttf", 16, '#FFFFFF', Image::WATER_SOUTH)->save($qr_code_file);

        return $qr_code_file;
    }

    /**
     * 获取粉丝列表
     */
    public function getFanList($p, $num = 10)
    {
        $wechatObj = self::$wechat_obj;
        if (!$access_token = $wechatObj->getAccessToken()) {
            return ['status' => -1, 'msg' => $wechatObj->getError()];
        }

        $p = intval($p) > 0 ? intval($p) : 1;
        $offset = ($p - 1) * $num;
        $max = 10000; //粉丝列表每次只能拉取的数量

        /* 获取所有粉丝列表openid并缓存 */
        $fans_key = 'wechat.fan_list';
        if (!$fans = Cache::get($fans_key)) {
            $next_openid = '';
            $fans = [];
            do {
                $ids = $wechatObj->getFanIdList($next_openid);
                if ($ids === false) {
                    return ['status' => -1, 'msg' => $wechatObj->getError()];
                }
                $fans = array_merge($fans, $ids['data']['openid']);
                $next_openid = $ids['next_openid'];
            } while ($ids['total'] > $max && $ids['count'] == $max);
            Cache::set($fans_key, $fans, 3600); //缓存列表一个小时
        }

        /* 获取指定粉丝，并获取详细信息 */
        $part_fans = array_slice($fans, $offset, $num);
        $user_list = [];
        $fan_key = 'wechat.fan_info';
        foreach ($part_fans as $openid) {
            if (!$fan = Cache::get($fan_key.'.'.$openid)) {
                $fan = $wechatObj->getFanInfo($openid, $access_token);
                if ($fan === false) {
                    continue;//不要因为一个粉丝的离开而影响整个列表
                }
                $fan['tags'] = $wechatObj->getFanTagNames($fan['tagid_list']);
                if ($fan['tags'] === false) {
                    continue;//不要因为一个粉丝的离开而影响整个列表
                }
                Cache::set($fan_key.'.'.$openid, $fan, 3600); //缓存粉丝一个小时
            }
            $user_list[$openid] = $fan;
        }

        return ['status' => 1, 'msg' => '获取成功', 'result' => [
            'total' => count($fans),
            'list' => $user_list
        ]];
    }

    /**
     * 商城用户里的粉丝列表
     */
    public function getUserFanList($p, $num = 10, $keyword= '')
    {
        $wechatObj = self::$wechat_obj;
        if (!$access_token = $wechatObj->getAccessToken()) {
            return ['status' => -1, 'msg' => $wechatObj->getError()];
        }

        $p = intval($p) > 0 ? intval($p) : 1;
        $condition = ['o.openid' => ['<>', ''], 'o.oauth' => 'weixin', 'o.oauth_child' => 'mp'];
        $keyword = trim($keyword);
        $keyword && $condition['o.openid|u.nickname'] = ['like', "%$keyword%"];

        $query = Db::name('oauth_users')->field('o.*')->alias('o')->join('__USERS__ u', 'u.user_id = o.user_id')->where($condition);
        $copyQuery = clone $query;
        $users = $query->page($p, $num)->select();
        $user_num = $copyQuery->count();

        $fan_key = 'wechat.user_fan_info';
        foreach ($users as &$user) {
            if (!$fan = Cache::get($fan_key.'.'.$user['openid'])) {
                $fan = $wechatObj->getFanInfo($user['openid'], $access_token);
                if ($fan === false) {
                    continue;//不要因为一个粉丝的离开而影响整个列表
                }
                Cache::set($fan_key.'.'.$user['openid'], $fan, 3600); //缓存粉丝一个小时
            }
            $user['weixin'] = $fan;
        }

        return ['status' => 1, 'msg' => '获取成功', 'result' => [
            'total' => $user_num,
            'list' => $users
        ]];
    }

    /**
     * 新建和更新文本素材
     * （图文素材只需保存在本地，微信不存储文本素材）
     */
    public function createOrUpdateText($material_id, $data)
    {
        $validate = new Validate([
            ['title','require|max:64','标题必填|标题最多64字'],
            ['content','require|max:600','内容必填|内容最多600字'],
        ]);
        if (!$validate->check($data)) {
            return ['status' => -1, 'msg' => $validate->getError()];
        }

        $text = [
            'type' => 'text',
            'update_time' => time(),
            'data' => [
                'title' => $data['title'],
                'content' => $data['content'],
            ]
        ];

        if ($material_id) {
            if (!$material = WxMaterial::get(['id' => $material_id, 'type' => WxMaterial::TYPE_TEXT])) {
                return ['status' => -1, 'msg' => '文本素材不存在'];
            }
            $material->save($text);
        } else {
            $material = WxMaterial::create($text);
        }

        return ['status' => 1, 'msg' => '素材提交成功！', 'result' => $material->id];
    }

    /**
     * 删除文本素材
     */
    public function deleteText($material_id)
    {
        if (!$material_id || !$material = WxMaterial::get(['id' => $material_id, 'type' => WxMaterial::TYPE_TEXT])) {
            return ['status' => -1, 'msg' => '文本素材不存在'];
        }

        $material->delete();

        return ['status' => 1, 'msg' => '删除文本素材成功'];
    }


    /**
     * 新建和更新图文素材
     */
    public function createOrUpdateNews($material_id, $news_id, $data)
    {
        $article = [
            "title"             => $data['title'],
            //"thumb_media_id"    => $data['thumb_media_id'],
            "thumb_url"         => $data['thumb_url'],
            "author"            => $data['author'],
            "digest"            => $data['digest'],
            "show_cover_pic"    => $data['show_cover_pic'] ? 1 : 0,
            "content"           => $data['content'],
            "content_source_url" => $data['content_source_url'],
            "material_id"       => $material_id,
            "update_time"       => time(),
        ];

        if ($material_id) {
            if (!$material = WxMaterial::get(['id' => $material_id, 'type' => WxMaterial::TYPE_NEWS])) {
                return ['status' => -1, 'msg' => '图文素材不存在'];
            }

            if ($news_id) {
                //更新单图文
                if (!$news = WxNews::get(['id' => $news_id, 'material_id' => $material_id])) {
                    return ['status' => -1, 'msg' => '单图文素材不存在'];
                }
                $news->save($article);
                if ($material->media_id) {
                    $material->save(['media_id' => 0]); // 需要重新上传
                }

            } else {
                //新增单图文
                $all_news = WxNews::all(['material_id' => $material_id]);
                $max_news_per_material = 8;
                if (count($all_news) >= $max_news_per_material) {
                    return ['status' => -1, 'msg' => "一个图文素材中的文章最多 $max_news_per_material 篇"];
                }
                WxNews::create($article);
            }
            $material->save([
                'update_time' => time(),
                'media_id' => 0 // 需要重新上传
            ]);

        } else {
            //新增多图文
            $material = WxMaterial::create([
                'type' => WxMaterial::TYPE_NEWS,
                'update_time' => time(),
            ]);
            $article['material_id'] = $material->id;
            WxNews::create($article);
        }

        //先不用上传到微信服务器，等实际使用的时候再上传

        return ['status' => 1, 'msg' => '素材提交成功！'];
    }

    /**
     * 删除图文素材
     * @param $material_id int 素材id
     * @return array
     */
    public function deleteNews($material_id)
    {
        if (!$material_id || !$material = WxMaterial::get(['id' => $material_id, 'type' => WxMaterial::TYPE_NEWS], 'wxNews')) {
            return ['status' => -1, 'msg' => '素材不存在'];
        }

        if (WxReply::get(['material_id' => $material_id, 'msg_type' => WxReply::MSG_NEWS])) {
            return ['status' => -1, 'msg' => '该素材正被自动回复使用，无法删除'];
        }

        if ($material->media_id) {
            self::$wechat_obj->delMaterial($material->media_id);
        }

        if (is_array($material->wx_news)) {
            foreach ($material->wx_news as $news) {
                $news->delete();
            }
        }
        $material->delete();

        return ['status' => 1, 'msg' => '删除图文成功'];
    }

    /**
     * 删除单图文
     * @param $news_id int 单图文的id
     * @return array
     */
    public function deleteSingleNews($news_id)
    {
        if (!$news_id || !$news = WxNews::get($news_id, 'wxMaterial')) {
            return ['status' => -1, 'msg' => '单图文素材不存在'];
        }

        if (!$news->wx_material) {
            return ['status' => -1, 'msg' => '该单图文所属素材不存在'];
        }

        if (count($news->wx_material->wx_news) == 1) {
            return $this->deleteNews($news->material_id);
        } else {
            if ($news->wx_material->media_id) {
                $news->wx_material->save(['media_id' => 0]); // 需要重新上传
            }
            $news->delete();
        }

        return ['status' => 1, 'msg' => '删除单图文成功'];
    }

    /**
     * 上传图文
     * @param $material WxMaterial
     * @return array
     */
    private function uploadNews($material)
    {
        $articles = [];
        foreach ($material->wx_news as $news) {
            // 1.获取或上传封面
            if ($thumb = WxMaterial::get(['type' => WxMaterial::TYPE_IMAGE, 'key' => md5($news['thumb_url'])])) {
                $thumb_media_id = $thumb->media_id;
            } else {
                $thumb = self::$wechat_obj->uploadMaterial('.'.$news['thumb_url'], 'image');
                if ($thumb ===  false) {
                    return ['status' => -1, 'msg' => self::$wechat_obj->getError()];
                }
                $thumb_media_id = $thumb['media_id'];
                WxMaterial::create([
                    'type' => WxMaterial::TYPE_IMAGE,
                    'key'  => md5($news['thumb_url']),
                    'media_id' => $thumb_media_id,
                    'update_time' => time(),
                    'data' => [
                        'url' => $news['thumb_url'],
                        'mp_url' => $thumb['url'],
                    ]
                ]);
            }

            // 2.将文章中的图片上传
            $news['content'] = htmlspecialchars_decode($news['content']);
            if (preg_match_all('#<img .*?src="(.*?)".*?/>#i', $news['content'], $matches)) {
                $imgs = array_unique($matches[1]);
                foreach ($imgs as $img) {
                    if (stripos($img, 'http') === 0) {
                        continue;
                    }

                    // 3.获取或上传文章中图片
                    if ($news_image = WxMaterial::get(['type' => WxMaterial::TYPE_NEWS_IMAGE, 'key' => md5($img)])) {
                        $news_image_url = $news_image->data['mp_url'];
                    } else {
                        $news_image_url = self::$wechat_obj->uploadNewsImage('.'.$img);
                        if ($news_image_url ===  false) {
                            return ['status' => -1, 'msg' => self::$wechat_obj->getError()];
                        }
                        WxMaterial::create([
                            'type' => WxMaterial::TYPE_NEWS_IMAGE,
                            'key'  => md5($img),
                            'update_time' => time(),
                            'data' => [
                                'url' => $news['thumb_url'],
                                'mp_url' => $news_image_url,
                            ]
                        ]);
                    }

                    $news['content'] = str_replace($img, $news_image_url, $news['content']);
                }
            }

            $articles[] = [
                "title"             => $news['title'],
                "thumb_media_id"    => $thumb_media_id,
                "author"            => $news['author'] ?: '',
                "digest"            => $news['digest'] ?: '',
                "show_cover_pic"    => $news['show_cover_pic'] ? 1 : 0,
                "content"           => $news['content'],
                "content_source_url" => $news['content_source_url'],
            ];
        }

        $news_media_id = self::$wechat_obj->uploadNews($articles);
        if ($news_media_id ===  false) {
            return ['status' => -1, 'msg' => self::$wechat_obj->getError()];
        }
        $material->save(['media_id' => $news_media_id]);

        return ['status' => 1, 'msg' => '上传成功', 'result' => $news_media_id];
    }

    /**
     * 发送图文消息
     * @param $material_id int 素材id
     * @param $openids array|string 可多个用户openid
     * @param int $to_all 0由openids决定，1所有粉丝
     * @return array
     */
    public function sendNewsMsg($material_id, $openids, $to_all = 0)
    {
        $material = WxMaterial::get(['id' => $material_id, 'type' => WxMaterial::TYPE_NEWS], 'wxNews');
        if (!$material || !$material->wx_news) {
            return ['status' => -1, 'msg' => '该素材不存在'];
        }

        if ($material->media_id) {
            $news_media_id = $material->media_id;
            if (false === self::$wechat_obj->getMaterial($material->media_id)) {
                $news_media_id = 0; //获取失败，可能被手动删了，需要重新上传
            }
        }
        if (empty($news_media_id)) {
            $return = $this->uploadNews($material);
            if ($return['status'] != 1) {
                return $return;
            }
            $news_media_id = $return['result'];
        }

        // 5.发送消息
        if ($to_all) {
            $result = self::$wechat_obj->sendMsgToAll(0, 'mpnews', $news_media_id);
        } else {
            $result = self::$wechat_obj->sendMsg($openids, 'mpnews', $news_media_id);
        }
        if ($result === false) {
            return ['status' => -1, 'msg' => self::$wechat_obj->getError()];
        }

        return ['status' => 1, 'msg' => '发送成功'];
    }

    /**
     * 删除图片
     * @param $url string 存储在本地的url
     */
    public function deleteImage($url)
    {
        if (strpos($url, 'weixin_mp_image/') === false) {
            return;
        }
        if (!$image = WxMaterial::get(['type' => WxMaterial::TYPE_IMAGE, 'key' => md5($url)])) {
            return;
        }
        if ($image->media_id) {
            self::$wechat_obj->delMaterial($image->media_id);
        }
    }

    /**
     * 系统默认模板消息
     * @return array
     */
    public function getDefaultTemplateMsg($template_sn = null)
    {
        $templates = [
            [
                "template_sn" => "TM00016",
                "title" => "订单提交成功",
                "content" =>
                    "{{first.DATA}}\n\n"
                    ."订单号：{{orderID.DATA}}\n"
                    ."待付金额：{{orderMoneySum.DATA}}\n"
                    ."{{backupFieldName.DATA}}{{backupFieldData.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM204987032",
                "title" => "订单支付成功通知",
                "content" =>
                    "{{first.DATA}}\n"
                    ."订单：{{keyword1.DATA}}\n"
                    ."支付状态：{{keyword2.DATA}}\n"
                    ."支付日期：{{keyword3.DATA}}\n"
                    ."商户：{{keyword4.DATA}}\n"
                    ."金额：{{keyword5.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM202243318",
                "title" => "订单发货通知",
                "content" =>
                    "{{first.DATA}}\n"
                    ."订单内容：{{keyword1.DATA}}\n"
                    ."物流服务：{{keyword2.DATA}}\n"
                    ."快递单号：{{keyword3.DATA}}\n"
                    ."收货信息：{{keyword4.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM401833445",
                "title" => "余额变动提示",
                "content" =>
                    "{{first.DATA}}\n"
                    ."变动时间：{{keyword1.DATA}}\n"
                    ."变动类型：{{keyword2.DATA}}\n"
                    ."变动金额：{{keyword3.DATA}}\n"
                    ."当前余额：{{keyword4.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM207126233",
                "title" => "分销商申请成功",
                "content" =>
                    "{{first.DATA}}\n"
                    ."分销商名称：{{keyword1.DATA}}\n"
                    ."分销商电话：{{keyword2.DATA}}\n"
                    ."申请时间：{{keyword3.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM201812627",
                "title" => "佣金提醒",
                "content" =>
                    "{{first.DATA}}\n"
                    ."佣金金额：{{keyword1.DATA}}\n"
                    ."时间：{{keyword2.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM407307456",
                "title" => "开团成功通知",
                "content" =>
                    "{{first.DATA}}\n"
                    ."商品名称：{{keyword1.DATA}}\n"
                    ."商品价格：{{keyword2.DATA}}\n"
                    ."组团人数：{{keyword3.DATA}}\n"
                    ."拼团类型：{{keyword4.DATA}}\n"
                    ."组团时间：{{keyword5.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM400048581",
                "title" => "参团成功通知",
                "content" =>
                    "{{first.DATA}}\n"
                    ."拼团名：{{keyword1.DATA}}\n"
                    ."拼团价：{{keyword2.DATA}}\n"
                    ."有效期：{{keyword3.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM407456411",
                "title" => "拼团成功通知",
                "content" =>
                    "{{first.DATA}}\n"
                    ."订单编号：{{keyword1.DATA}}\n"
                    ."团购商品：{{keyword2.DATA}}\n"
                    ."{{remark.DATA}}",
            ], [
                "template_sn" => "OPENTM400940587",
                "title" => "拼团退款提醒",
                "content" =>
                    "{{first.DATA}}\n"
                    ."单号：{{keyword1.DATA}}\n"
                    ."商品：{{keyword2.DATA}}\n"
                    ."原因：{{keyword3.DATA}}\n"
                    ."退款：{{keyword4.DATA}}\n"
                    ."{{remark.DATA}}",
            ]
        ];

        $templates = convert_arr_key($templates, 'template_sn');

        $valid_sns = ['OPENTM204987032', 'OPENTM202243318']; //目前支持的模板
        $valid_templates = [];
        foreach ($valid_sns as $sn) {
            if (isset($templates[$sn])) {
                $valid_templates[$sn] = $templates[$sn];
            }
        }

        if ($template_sn) {
            return $valid_templates[$template_sn];
        }
        return $valid_templates;
    }

    /**
     * 配置模板
     * @param $data array 配置
     */
    public function setTemplateMsg($template_sn, $data)
    {
        if (!isset($data['is_use']) && !isset($data['remark'])) {
            return ['status' => -1, 'msg' => '参数为空'];
        }

        $tpls = $this->getDefaultTemplateMsg();
        if (!key_exists($template_sn, $tpls)) {
            return ['status' => -1, 'msg' => "模板消息的编号[$template_sn]不存在"];
        }

        if ($tpl_msg = WxTplMsg::get(['template_sn' => $template_sn])) {
            $tpl_msg->save($data);
        } else {
            if (!$template_id = self::$wechat_obj->addTemplateMsg($template_sn)) {
                return ['status' => -1, 'msg' => self::$wechat_obj->getError()];
            }
            WxTplMsg::create([
                'template_id' => $template_id,
                'template_sn' => $template_sn,
                'title' => $tpls[$template_sn]['title'],
                'is_use' => isset($data['is_use']) ? $data['is_use'] : 0,
                'remark' => isset($data['remark']) ? $data['remark'] : '',
                'add_time' => time(),
            ]);
        }

        return ['status' => 1, 'msg' => '操作成功'];
    }

    /**
     * 重置模板消息
     */
    public function resetTemplateMsg($template_sn)
    {
        if (!$template_sn) {
            return ['status' => -1, 'msg' => '参数不为空'];
        }

        if ($tpl_msg = WxTplMsg::get(['template_sn' => $template_sn])) {
            if ($tpl_msg->template_id) {
                self::$wechat_obj->delTemplateMsg($tpl_msg->template_id);
            }
            $tpl_msg->delete();
        }

        return ['status' => 1, 'msg' => '操作成功'];
    }

    /**
     * 发送模板消息（订单支付成功通知）
     * @param $order array 订单数据
     */
    public function sendTemplateMsgOnPaySuccess($order)
    {
        if ( ! $order) {
            return ['status' => -1, 'msg' => '订单不存在'];
        }

        $template_sn = 'OPENTM204987032';
        if ( ! $this->getDefaultTemplateMsg($template_sn)) {
            return ['status' => -1, 'msg' => '消息模板不存在'];
        }

        $tpl_msg = WxTplMsg::get(['template_sn' => $template_sn, 'is_use' => 1]);
        if ( ! $tpl_msg || ! $tpl_msg->template_id) {
            return ['status' => -1, 'msg' => '消息模板未开启'];
        }

        $user = Db::name('oauth_users')->where(['user_id' => $order['user_id'], 'oauth' => 'weixin', 'oauth_child' => 'mp'])->find();
        if ( ! $user || ! $user['openid']) {
            return ['status' => -1, 'msg' => '用户不存在或不是微信用户'];
        }
    
        $store_name = tpCache('shop_info.store_name');
        $data = [
            'first' => ['value' => '订单支付成功！'],
            'keyword1' => ['value' => $order['order_sn']],
            'keyword2' => ['value' => '已支付'],
            'keyword3' => ['value' => date('Y-m-d H:i', $order['pay_time'])],
            'keyword4' => ['value' => $store_name],
            'keyword5' => ['value' => $order['order_amount']],
            'remark' => ['value' => $tpl_msg->remark ?: ''],
        ];

        $url = SITE_URL.url('/mobile/order/order_detail?id='.$order['order_id']);
        $return = self::$wechat_obj->sendTemplateMsg($user['openid'], $tpl_msg->template_id, $url, $data);
        if ($return === false) {
            return ['status' => -1, 'msg' => self::$wechat_obj->getError()];
        }

        return ['status' => 1, 'msg' => '发送模板消息成功'];
    }

    /**
     * 发送模板消息（订单发货通知）
     * @param $deliver array 物流信息
     */
    public function sendTemplateMsgOnDeliver($deliver)
    {
        if ( ! $deliver) {
            return ['status' => -1, 'msg' => '订单物流不存在'];
        }

        $template_sn = 'OPENTM202243318';
        if ( ! $this->getDefaultTemplateMsg($template_sn)) {
            return ['status' => -1, 'msg' => '消息模板不存在'];
        }

        $tpl_msg = WxTplMsg::get(['template_sn' => $template_sn, 'is_use' => 1]);
        if ( ! $tpl_msg || ! $tpl_msg->template_id) {
            return ['status' => -1, 'msg' => '消息模板未开启'];
        }

        $user = Db::name('oauth_users')->where(['user_id' => $deliver['user_id'], 'oauth' => 'weixin', 'oauth_child' => 'mp'])->find();
        if ( ! $user || ! $user['openid']) {
            return ['status' => -1, 'msg' => '用户不存在或不是微信用户'];
        }

        // 收货地址
        $province = getRegionName($deliver['province']);
        $city = getRegionName($deliver['city']);
        $district = getRegionName($deliver['district']);
        $full_address = $province.' '.$city.' '.$district.' '. $deliver['address'];

        $order_goods = Db::name('order_goods')->where('order_id', $deliver['order_id'])->find();
        $data = [
            'first' => ['value' => "订单{$deliver['order_sn']}发货成功！"],
            'keyword1' => ['value' => $order_goods['goods_name']],
            'keyword2' => ['value' => $deliver['shipping_name']],
            'keyword3' => ['value' => $deliver['delivery_sn']],
            'keyword4' => ['value' => $full_address],
            'remark' => ['value' => $tpl_msg->remark ?: ''],
        ];

        $url = SITE_URL.url('/mobile/order/order_detail?id='.$deliver['order_id']);
        $return = self::$wechat_obj->sendTemplateMsg($user['openid'], $tpl_msg->template_id, $url, $data);
        if ($return === false) {
            return ['status' => -1, 'msg' => self::$wechat_obj->getError()];
        }

        return ['status' => 1, 'msg' => '发送模板消息成功'];
    }

    /**
     * 图片插件中展示的列表
     * @param $size int 拉取多少
     * @param $start int 开始位置
     * @return string
     */
    public function getPluginImages($size, $start = 0)
    {
        $data = self::$wechat_obj->getMaterialList('image', $size * $start, $size);
        if ($data === false) {
            return json_encode([
                "state" => self::$wechat_obj->getError(),
                "list" => [],
                "start" => $start,
                "total" => 0
            ]);
        }

        $list = [];
        foreach ($data['item'] as $item) {
            $list[] = [
                'url' => $item['url'],
                'mtime' => $item['update_time'],
                'name' => $item['name'],
            ];
        }

        return json_encode([
            "state" => "no match file",
            "list" => $list,
            "start" => $start,
            "total" => $data['total_count']
        ]);
    }

    /**
     * 修正关键字
     * @param $keywords
     * @return array
     */
    private function trimKeywords($keywords)
    {
        $keywords = explode(',', $keywords);
        $keywords = array_map('trim', $keywords);
        $keywords = array_unique($keywords);
        foreach ($keywords as $k => $keyword) {
            if (!$keyword) {
                unset($keywords[$k]);
            }
        }

        return array_values($keywords);
    }

    /**
     * 更新关键字
     * @param $reply_id int 回复id
     * @param $wx_keywords WxKeyword[]
     * @param $keywords array 关键字数组
     */
    private function updateKeywords($reply_id, $wx_keywords, $keywords)
    {
        $wx_keywords = convert_arr_key($wx_keywords, 'keyword');

        //先删除不存在的keyword
        foreach ($wx_keywords as $key => $word) {
            if (!in_array($key, $keywords)) {
                $word->delete();
                unset($wx_keywords[$key]);
            }
        }
        //创建要设置的keyword
        foreach ($keywords as $keyword) {
            if (!isset($wx_keywords[$keyword])) {
                WxKeyword::create([
                    'keyword' => $keyword,
                    'pid' => $reply_id,
                    'type' => WxKeyword::TYPE_AUTO_REPLY
                ]);
            }
        }
    }

    /**
     * 检查文本自动回复表单
     */
    private function checkTextAutoReplyForm(&$data)
    {
        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            $rules = [
                ['type', 'require', '回复类型必需'],
                ['keywords','require','关键词必填'],
                ['rule','require|max:32','规则名必填|规则名最多32字'],
                ['content','require|max:600','文本内容必填|文本内容最多600字'],
            ];
        } else {
            $rules = [
                ['type', 'require', '回复类型必需'],
                ['content','max:600','文本内容最多600字'],
            ];
        }
        $validate = new Validate($rules);
        if (!$validate->check($data)) {
            return ['status' => -1, 'msg' => $validate->getError()];
        }

        if ( ! key_exists($data['type'], WxReply::getAllType())) {
            return ['status' => -1, 'msg' => '回复类型不存在'];
        }

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            if (!$data['keywords'] = $this->trimKeywords($data['keywords'])) {
                return ['status' => -1, 'msg' => '关键字不存在'];
            }
        }

        return ['status' => 1, 'msg' => '检查成功'];
    }

    /**
     * 添加文本自动回复
     */
    public function addTextAutoReply($data)
    {
        $return = $this->checkTextAutoReplyForm($data);
        if ($return['status'] != 1) {
            return $return;
        }

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            if (WxKeyword::get(['keyword' => ['in', $data['keywords']], 'type' => WxKeyword::TYPE_AUTO_REPLY])) {
                return ['status' => -1, 'msg' => '有关键字被其他规则使用'];
            }
        }

        $reply = WxReply::create([
            'rule' => $data['rule'],
            'update_time' => time(),
            'type' => $data['type'],
            'msg_type' => WxReply::MSG_TEXT,
            'data' => $data['content'],
        ]);

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            foreach ($data['keywords'] as $keyword) {
                WxKeyword::create([
                    'keyword' => $keyword,
                    'pid' => $reply->id,
                    'type' => WxKeyword::TYPE_AUTO_REPLY
                ]);
            }
        }

        return ['status' => 1, 'msg' => '添加成功'];
    }

    /**
     * 更新文本自动回复
     * @param $reply_id int 回复id
     * @param $data array
     * @return array
     */
    public function updateTextAutoReply($reply_id, $data)
    {
        $return = $this->checkTextAutoReplyForm($data);
        if ($return['status'] != 1) {
            return $return;
        }

        $with = ($data['type'] == WxReply::TYPE_KEYWORD) ? 'wxKeywords' : [];
        if (!$reply = WxReply::get(['id' => $reply_id], $with)) {
            return ['status' => -1, 'msg' => '该自动回复不存在'];
        }

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            $keyword_ids = get_arr_column($reply->wx_keywords, 'id');
            if (WxKeyword::all(['keyword' => ['in', $data['keywords']], 'type' => WxKeyword::TYPE_AUTO_REPLY, 'id' => ['not in', $keyword_ids]])) {
                return ['status' => -1, 'msg' => '有关键字被其他规则使用'];
            }

            $this->updateKeywords($reply_id, $reply->wx_keywords, $data['keywords']);
        }

        $reply->save([
            'rule' => $data['rule'],
            'update_time' => time(),
            'data' => $data['content'],
            'material_id' => 0,
            'msg_type' => WxReply::MSG_TEXT
        ]);

        return ['status' => 1, 'msg' => '更新成功'];
    }

    /**
     * 检查文本自动回复表单
     */
    private function checkNewsAutoReplyForm(&$data)
    {
        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            $rules = [
                ['keywords','require','关键词必填'],
                ['rule','require|max:32','规则名必填|规则名最多32字'],
                ['type', 'require', '回复类型必需'],
                ['material_id','require','关联素材id必需'],
            ];
        } else {
            $rules = [
                ['type', 'require', '回复类型必需'],
                ['material_id','require','关联素材id必需'],
            ];
        }
        $validate = new Validate($rules);
        if (!$validate->check($data)) {
            return ['status' => -1, 'msg' => $validate->getError()];
        }

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            if (!$data['keywords'] = $this->trimKeywords($data['keywords'])) {
                return ['status' => -1, 'msg' => '关键字不存在'];
            }
        }

        if (!WxMaterial::get(['id' => $data['material_id'], 'type' => WxMaterial::TYPE_NEWS])) {
            return ['status' => -1, 'msg' => '关联图文素材不存在'];
        }

        return ['status' => 1, 'msg' => '检查成功'];
    }

    /**
     * 新增图文自动回复
     */
    public function addNewsAutoReply($data)
    {
        $return = $this->checkNewsAutoReplyForm($data);
        if ($return['status'] != 1) {
            return $return;
        }

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            if (WxKeyword::get(['keyword' => ['in', $data['keywords']], 'type' => WxKeyword::TYPE_AUTO_REPLY])) {
                return ['status' => -1, 'msg' => '有关键字被其他规则使用'];
            }
        }

        $reply = WxReply::create([
            'rule' => $data['rule'],
            'update_time' => time(),
            'type' => $data['type'],
            'msg_type' => WxReply::MSG_NEWS,
            'material_id' => $data['material_id'],
        ]);

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            foreach ($data['keywords'] as $keyword) {
                WxKeyword::create([
                    'keyword' => $keyword,
                    'pid' => $reply->id,
                    'type' => WxKeyword::TYPE_AUTO_REPLY
                ]);
            }
        }

        return ['status' => 1, 'msg' => '添加成功'];
    }

    /**
     * 更新图文自动回复
     * @param $reply_id int 回复id
     * @param $data array
     * @return array
     */
    public function updateNewsAutoReply($reply_id, $data)
    {
        $return = $this->checkNewsAutoReplyForm($data);
        if ($return['status'] != 1) {
            return $return;
        }

        $with = ($data['type'] == WxReply::TYPE_KEYWORD) ? 'wxKeywords' : [];
        if (!$reply = WxReply::get(['id' => $reply_id], $with)) {
            return ['status' => -1, 'msg' => '该自动回复不存在'];
        }

        if ($data['type'] == WxReply::TYPE_KEYWORD) {
            $keyword_ids = get_arr_column($reply->wx_keywords, 'id');
            if (WxKeyword::all(['keyword' => ['in', $data['keywords']], 'type' => WxKeyword::TYPE_AUTO_REPLY, 'id' => ['not in', $keyword_ids]])) {
                return ['status' => -1, 'msg' => '有关键字被其他规则使用'];
            }

            $this->updateKeywords($reply_id, $reply->wx_keywords, $data['keywords']);
        }

        $reply->save([
            'rule' => $data['rule'],
            'update_time' => time(),
            'material_id' => $data['material_id'],
            'msg_type' => WxReply::MSG_NEWS,
            'data' => '',
        ]);

        return ['status' => 1, 'msg' => '更新成功'];
    }

    /**
     * 添加自动回复
     */
    public function addAutoReply($type, $data)
    {
        if ($type == 'text') {
            return $this->addTextAutoReply($data);
        } elseif ($type == 'news') {
            return $this->addNewsAutoReply($data);
        } else {
            return ['status' => -1, 'msg' => '自动回复类型不存在'];
        }
    }

    /**
     * 更新自动回复
     */
    public function updateAutoReply($type, $reply_id, $data)
    {
        if ($type == 'text') {
            return $this->updateTextAutoReply($reply_id, $data);
        } elseif ($type == 'news') {
            return $this->updateNewsAutoReply($reply_id, $data);
        } else {
            return ['status' => -1, 'msg' => '自动回复类型不存在'];
        }
    }

    /**
     * 删除自动回复
     */
    public function deleteAutoReply($reply_id)
    {
        if (!$reply = WxReply::get(['id' => $reply_id])) {
            return ['status' => -1, 'msg' => '该自动回复不存在'];
        }

        if ($reply->type == WxReply::TYPE_KEYWORD) {
            WxKeyword::where(['pid' => $reply_id])->delete();
        }

        $reply->delete();

        return ['status' => 1, 'msg' => '删除成功'];
    }

    //微信公众平台返回错误码对应含义
    public function geterror($rs){
        if(is_object($rs)) $rs = (array)$rs;
        $err = array('-1'=>'系统繁忙','0'=>'请求成功','40001'=>'不合法的调用凭证','40002'=>'不合法的凭证类型','40003'=>'不合法的OpenID','40004'=>'不合法的媒体文件类型','40005'=>'不合法的文件类型','40006'=>'不合法的文件大小','40007'=>'不合法的media_id','40008'=>'不合法的消息类型','40009'=>'不合法的图片大小','40010'=>'不合法的语音大小','40011'=>'不合法的视频大小','40012'=>'不合法的缩略图大小','40013'=>'不合法的AppID','40014'=>'不合法的access_token','40015'=>'不合法的菜单类型','40016'=>'不合法的按钮个数','40017'=>'不合法的按钮类型','40018'=>'不合法的按钮名称长度','40019'=>'不合法的按钮KEY长度','40019'=>'不合法的按钮KEY长度','40020'=>'不合法的url长度','40021'=>'不合法的菜单版本号','40022'=>'不合法的子菜单级数','40023'=>'不合法的子菜单按钮个数','40024'=>'不合法的子菜单类型','40025'=>'不合法的子菜单按钮名称长度','40026'=>'不合法的子菜单按钮KEY长度','40027'=>'不合法的子菜单按钮url长度','40028'=>'不合法的自定义菜单使用用户','40029'=>'不合法或已过期的code','40030'=>'不合法的refresh_token','40031'=>'不合法的 openid 列表','40032'=>'不合法的 openid 列表长度','40033'=>'不合法的请求字符','40035'=>'不合法的参数','40036'=>'不合法的template_id长度','40037'=>'不合法的template_id','40038'=>'不合法的请求格式','40039'=>'不合法的url长度','40048'=>'不合法的url域名','40050'=>'不合法的分组 id','40051'=>'分组名字不合法','40054'=>'不合法的子菜单url域名','40055'=>'不合法的菜单url域名','40056'=>'不合法的agentid','40057'=>'不合法的callbackurl或者callbackurl验证失败','40058'=>'不合法的参数','40059'=>'不合法的上报地理位置标志位','40060'=>'删除单篇图文时，指定的 article_idx 不合法','40063'=>'参数为空','40066'=>'不合法的url或部门列表','40068'=>'不合法的标签ID','40070'=>'指定的标签范围结点全部无效','40071'=>'不合法的标签名字','40072'=>'不合法的标签名字长度','40073'=>'不合法的openid','40074'=>'news消息不支持保密消息类型','40077'=>'不合法的pre_auth_code参数','40078'=>'不合法的auth_code参数','40080'=>'不合法的suite_secret','40082'=>'不合法的suite_token','40083'=>'不合法的suite_id','40084'=>'不合法的permanent_code参数','40085'=>'不合法的的suite_ticket参数','40086'=>'不合法的第三方应用appid','40088'=>'jobid不存在','40089'=>'批量任务的结果已清理','40091'=>'secret不合法','40092'=>'导入文件存在不合法的内容','40093'=>'不合法的jsapi_ticket参数','40094'=>'不合法的URL','40096'=>'不合法的外部联系人userid','40097'=>'参数错误','40098'=>'接替成员尚未实名认证','40099'=>'接替成员的外部联系人数量已达上限','40100'=>'此用户的外部联系人已经在转移流程中','40117'=>'分组名字不合法','40118'=>'media_id 大小不合法','40119'=>'button 类型错误','40120'=>'button 类型错误','40121'=>'不合法的 media_id 类型','40125'=>'无效的appsecret','40132'=>'微信号不合法','40137'=>'不支持的图片格式','40155'=>'请勿添加其他公众号的主页链接','40163'=>'oauth_code已使用','41001'=>'缺失access_token参数','41002'=>'缺失appid参数','41003'=>'缺失refresh_token参数','41004'=>'缺失secret参数','41005'=>'缺少多媒体文件数据','41006'=>'缺失media_id参数','41007'=>'缺失子菜单数据','41008'=>'缺失code参数','41009'=>'缺失openid参数','41010'=>'缺失url参数','41011'=>'缺少agentid参数','41016'=>'缺少title参数','41017'=>'缺少tagid参数','41019'=>'缺少 department 参数','41021'=>'缺少suite_id参数','41022'=>'缺少suite_access_token参数','41023'=>'缺少suite_ticket参数','41024'=>'缺少secret参数','41025'=>'缺少permanent_code参数','41033'=>'缺少 description 参数','41035'=>'缺少外部联系人userid参数','42001'=>'access_token已过期','42002'=>'refresh_token超时','42003'=>'code超时','42007'=>'pre_auth_code已过期','42009'=>'suite_access_token已过期','43001'=>'需要使用GET方法请求','43002'=>'需要使用POST方法请求','43003'=>'需要使用HTTPS','43004'=>'需要接收者关注','43005'=>'需要好友关系','43019'=>'需要将接收者从黑名单中移除','44001'=>'多媒体文件为空','44002'=>'POST 的数据包为空','44003'=>'图文消息内容为空','44004'=>'文本消息内容为空','44005'=>'空白的列表','45001'=>'多媒体文件大小超过限制','45002'=>'消息内容大小超过限制','45003'=>'标题字段超过限制','45004'=>'描述字段超过限制','45005'=>'链接字段超过限制','45006'=>'图片链接字段超过限制','45007'=>'语音播放时间超过限制','45008'=>'图文消息超过限制','45009'=>'接口调用超过限制','45010'=>'创建菜单个数超过限制','45011'=>'API 调用太频繁，请稍候再试','45012'=>'模板大小超过限制','45015'=>'回复时间超过限制','45016'=>'不能修改默认组','45017'=>'分组名字过长','45018'=>'分组数量超过上限','45022'=>'应用name参数长度不符合系统限制','45024'=>'帐号数量超过上限','45026'=>'已添加的模板数量超过限制','45032'=>'图文消息author参数长度超过限制','45033'=>'接口并发调用超过限制','45047'=>'客服接口下行条数超过上限','45064'=>'创建菜单包含未关联的小程序','45065'=>'相同 clientmsgid 已存在群发记录，返回数据中带有已存在的群发任务的 msgid','45066'=>'相同 clientmsgid 重试速度过快，请间隔1分钟重试','45067'=>'clientmsgid 长度超过限制','46001'=>'不存在媒体数据','46002'=>'不存在的菜单版本','46003'=>'不存在的菜单数据','46004'=>'指定的用户不存在','47001'=>'解析 JSON/XML 内容错误','48001'=>'api 功能未授权，请确认公众号已获得该接口，可以在公众平台官网 - 开发者中心页中查看接口权限','48002'=>'粉丝拒收消息（粉丝在公众号选项中，关闭了 “ 接收消息 ” ）','48003'=>'不合法的suite_id','48004'=>'api 接口被封禁或授权关系无效','48005'=>'api 禁止删除被自动回复和自定义菜单引用的素材或API接口已废弃','48006'=>'api 禁止清零调用次数，因为清零次数达到上限','48008'=>'没有该类型消息的发送权限','50001'=>'接口未授权或redirect_url未登记可信域名','50002'=>'用户受限，可能是违规后接口被封禁','50003'=>'应用已禁用','50005'=>'用户未关注公众号','53010'=>'名称格式不合法','53011'=>'名称检测命中频率限制','53012'=>'禁止使用该名称','53013'=>'公众号：名称与已有公众号名称重复;小程序：该名称与已有小程序名称重复','53014'=>'公众号：公众号已有{名称A+}时，需与该帐号相同主体才可申请{名称A};小程序：小程序已有{名称A+}时，需与该帐号相同主体才可申请{名称A}','53015'=>'公众号：该名称与已有小程序名称重复，需与该小程序帐号相同主体才可申请;小程序：该名称与已有公众号名称重复，需与该公众号帐号相同主体才可申请','53016'=>'公众号：该名称与已有多个小程序名称重复，暂不支持申请;小程序：该名称与已有多个公众号名称重复，暂不支持申请','53017'=>'公众号：小程序已有{名称A+}时，需与该帐号相同主体才可申请{名称A};小程序：公众号已有{名称A+}时，需与该帐号相同主体才可申请{名称A}','53018'=>'名称命中微信号','53019'=>'名称在保护期内','53200'=>'本月功能介绍修改次数已用完','53201'=>'功能介绍内容命中黑名单关键字','53202'=>'本月头像修改次数已用完','53300'=>'超出每月次数限制','53301'=>'超出可配置类目总数限制','53302'=>'当前账号主体类型不允许设置此种类目','53303'=>'提交的参数不合法','53304'=>'与已有类目重复','53305'=>'包含未通过IPC校验的类目','53306'=>'修改类目只允许修改类目资质，不允许修改类目ID','53307'=>'只有审核失败的类目允许修改','53308'=>'审核中的类目不允许删除','60001'=>'部门长度不符合限制','60003'=>'部门ID不存在','60004'=>'父部门不存在','60005'=>'部门下存在成员','60006'=>'部门下存在子部门','60007'=>'不允许删除根部门','60008'=>'部门已存在','60009'=>'部门名称含有非法字符','60010'=>'部门存在循环关系','60011'=>'指定的成员/部门/标签参数无权限','60012'=>'不允许删除默认应用','60020'=>'访问ip不在白名单之中','60028'=>'不允许修改第三方应用的主页 URL','60102'=>'UserID已存在','60103'=>'手机号码不合法','60104'=>'手机号码已存在','60105'=>'邮箱不合法','60106'=>'邮箱已存在','60107'=>'微信号不合法','60110'=>'用户所属部门数量超过限制','60111'=>'UserID不存在','60112'=>'成员name参数不合法','60123'=>'无效的部门id','60124'=>'无效的父部门id','60125'=>'非法部门名字','60127'=>'缺少department参数','60129'=>'成员手机和邮箱都为空','61450'=>'系统错误 (system error)','61451'=>'参数错误 (invalid parameter)','61452'=>'无效客服账号 (invalid kf_account)','61453'=>'客服帐号已存在 (kf_account exsited)','61454'=>'客服帐号名长度超过限制 ( 仅允许 10 个英文字符，不包括 @ 及 @ 后的公众号的微信号 )(invalid kf_acount length)','61455'=>'客服帐号名包含非法字符 ( 仅允许英文 + 数字 )(illegal character in kf_account)','61456'=>'客服帐号个数超过限制 (10 个客服账号 )(kf_account count exceeded)','61457'=>'无效头像文件类型 (invalid file type)','61500'=>'日期格式错误','65301'=>'不存在此 menuid 对应的个性化菜单','65302'=>'没有相应的用户','65303'=>'没有默认菜单，不能创建个性化菜单','65304'=>'MatchRule 信息为空','65305'=>'个性化菜单数量受限','65306'=>'不支持个性化菜单的帐号','65307'=>'个性化菜单信息为空','65308'=>'包含没有响应类型的 button','65309'=>'个性化菜单开关处于关闭状态','65310'=>'填写了省份或城市信息，国家信息不能为空','65311'=>'填写了城市信息，省份信息不能为空','65312'=>'不合法的国家信息','65313'=>'不合法的省份信息','65314'=>'不合法的城市信息','65316'=>'该公众号的菜单设置了过多的域名外跳（最多跳转到 3 个域名的链接）','65317'=>'不合法的 URL','72023'=>'发票已被其他公众号锁定','72024'=>'发票状态错误','72037'=>'存在发票不属于该用户','80001'=>'可信域名不正确，或者无ICP备案','81001'=>'部门下的结点数超过限制（3W）','81002'=>'部门最多15层','81011'=>'无权限操作标签','81013'=>'UserID、部门ID、标签ID全部非法或无权限','81014'=>'标签添加成员，单次添加user或party过多','82001'=>'指定的成员/部门/标签全部无效','82002'=>'不合法的PartyID列表长度','82003'=>'不合法的TagID列表长度','84014'=>'成员票据过期','84015'=>'成员票据无效','84019'=>'缺少templateid参数','84020'=>'templateid不存在','84021'=>'缺少register_code参数','84022'=>'无效的register_code参数','84023'=>'不允许调用设置通讯录同步完成接口','84024'=>'无注册信息','84025'=>'不符合的state参数','84052'=>'缺少caller参数','84053'=>'缺少callee参数','84054'=>'缺少auth_corpid参数','84055'=>'超过拨打公费电话频率','84056'=>'被拨打用户安装应用时未授权拨打公费电话权限','84057'=>'公费电话余额不足','84058'=>'caller 呼叫号码不支持','84059'=>'号码非法','84060'=>'callee 呼叫号码不支持','84061'=>'不存在外部联系人的关系','84062'=>'未开启公费电话应用','84063'=>'caller不存在','84064'=>'callee不存在','84065'=>'caller跟callee电话号码一致','84066'=>'服务商拨打次数超过限制','84067'=>'管理员收到的服务商公费电话个数超过限制','84071'=>'不合法的外部联系人授权码','84072'=>'应用未配置客服','84073'=>'客服userid不在应用配置的客服列表中','84074'=>'没有外部联系人权限','85001'=>'微信号不存在或微信号设置为不可搜索','85002'=>'小程序绑定的体验者数量达到上限','85002'=>'包含不合法的词语','85003'=>'微信号绑定的小程序体验者达到上限','85004'=>'微信号已经绑定','85004'=>'每企业每个月设置的可信域名不可超过20个','85005'=>'可信域名未通过所有权校验','85006'=>'标签格式错误','85007'=>'页面路径错误','85008'=>'类目填写错误','85009'=>'已经有正在审核的版本','85010'=>'item_list有项目为空','85011'=>'标题填写错误','85012'=>'无效的审核id','85012'=>'无效的审核id','85013'=>'无效的自定义配置','85014'=>'无效的模版编号','85015'=>'该账号不是小程序账号','85015'=>'版本输入错误','85016'=>'域名数量超过限制','85017'=>'没有新增域名，请确认小程序已经添加了域名或该域名是否没有在第三方平台添加','85018'=>'域名没有在第三方平台设置','85019'=>'没有审核版本','85020'=>'审核状态未满足发布','85023'=>'审核列表填写的项目数不在1-5以内','85026'=>'微信号绑定管理员名额达到上限','85027'=>'身份证绑定管理员名额达到上限','85043'=>'模版错误','85044'=>'代码包超过大小限制','85045'=>'ext_json有不存在的路径','85046'=>'tabBar中缺少path','85047'=>'pages字段为空','85048'=>'ext_json解析失败','85060'=>'无效的taskid','85061'=>'手机号绑定管理员名额达到上限','85062'=>'手机号黑名单','85063'=>'身份证黑名单','85064'=>'找不到模版','85064'=>'找不到模版','85064'=>'找不到草稿','85064'=>'找不到草稿','85065'=>'模版库已满','85066'=>'链接错误','85068'=>'测试链接不是子链接','85069'=>'校验文件失败','85070'=>'链接为黑名单','85071'=>'已添加该链接，请勿重复添加','85072'=>'该链接已被占用','85073'=>'二维码规则已满','85074'=>'小程序未发布, 小程序必须先发布代码才可以发布二维码跳转规则','85075'=>'个人类型小程序无法设置二维码规则','85076'=>'链接没有ICP备案','85077'=>'小程序类目信息失效（类目中含有官方下架的类目，请重新选择类目）','85079'=>'小程序没有线上版本，不能进行灰度','85080'=>'小程序提交的审核未审核通过','85081'=>'无效的发布比例','85082'=>'当前的发布比例需要比之前设置的高','85083'=>'搜索标记位被封禁，无法修改','85084'=>'非法的status值，只能填0或者1','85085'=>'近7天提交审核的小程序数量过多，请耐心等待审核完毕后再次提交','85086'=>'提交代码审核之前需提前上传代码','85087'=>'小程序已使用api navigateToMiniProgram，请声明跳转appid列表后再次提交','86000'=>'不是由第三方代小程序进行调用','86000'=>'不是由第三方代小程序进行调用','86000'=>'不是由第三方代小程序进行调用','86001'=>'不存在第三方的已经提交的代码','86001'=>'不存在第三方的已经提交的代码','86001'=>'不存在第三方的已经提交的代码','86001'=>'参数 chatid 不合法','86002'=>'小程序未初始化完成，请确保已设置小程序昵称、头像、简介、服务类目','86003'=>'参数 chatid 不存在','86004'=>'参数 群名不合法','86005'=>'参数 群主不合法','86006'=>'群成员数过多或过少','86007'=>'不合法的群成员','86008'=>'非法操作非自己创建的群','86101'=>'仅群主才有操作权限','86201'=>'参数 需要chatid','86202'=>'参数 需要群名','86203'=>'参数 需要群主','86204'=>'参数 需要群成员','86205'=>'参数 字符串chatid过长','86206'=>'参数 数字chatid过大','86207'=>'群主不在群成员列表','86215'=>'会话ID已经存在','86216'=>'存在非法会话成员ID','86217'=>'会话发送者不在会话成员列表中','86220'=>'指定的会话参数不合法','87011'=>'现网已经在灰度发布，不能进行版本回退','87012'=>'该版本不能回退，可能的原因：1:无上一个线上版用于回退 2:此版本为已回退版本，不能回退 3:此版本为回退功能上线之前的版本，不能回退','87013'=>'撤回次数达到上限（每天一次，每个月10次）','89000'=>'该公众号 / 小程序 已经绑定了开放平台帐号','89001'=>'not same contractor，Authorizer与开放平台帐号主体不相同','89001'=>'not same contractor，Authorizer与开放平台帐号主体不相同','89002'=>'open not exists，该公众号/小程序未绑定微信开放平台帐号。','89003'=>'该开放平台帐号并非通过api创建，不允许操作','89003'=>'该开放平台帐号并非通过api创建，不允许操作','89004'=>'该开放平台帐号所绑定的公众号/小程序已达上限（100个）','89019'=>'业务域名无更改，无需重复设置','89020'=>'尚未设置小程序业务域名，请先在第三方平台中设置小程序业务域名后在调用本接口','89021'=>'请求保存的域名不是第三方平台中已设置的小程序业务域名或子域名','89029'=>'业务域名数量超过限制','89231'=>'个人小程序不支持调用setwebviewdomain 接口','89236'=>'该插件不能申请','89237'=>'已经添加该插件','89238'=>'申请或使用的插件已经达到上限','89239'=>'该插件不存在','89256'=>'token信息有误','89257'=>'该插件版本不支持快速更新','89258'=>'当前小程序帐号存在灰度发布中的版本，不可操作快速更新','90001'=>'未认证摇一摇周边','90002'=>'缺少摇一摇周边ticket参数','90003'=>'摇一摇周边ticket参数不合法','90100'=>'非法的对外属性类型','90101'=>'对外属性：文本类型长度不合法','90102'=>'对外属性：网页类型标题长度不合法','90103'=>'对外属性：网页url不合法','90104'=>'对外属性：小程序类型标题长度不合法','90105'=>'对外属性：小程序类型pagepath不合法','90106'=>'对外属性：请求参数不合法','91001'=>'不是公众号快速创建的小程序','91002'=>'小程序发布后不可改名','91003'=>'改名状态不合法','91004'=>'昵称不合法','91005'=>'昵称命中主体保护','91006'=>'昵称命中微信号','91007'=>'昵称已被占用','91008'=>'昵称命中7天侵权保护期','91009'=>'需要提交材料','91010'=>'其他错误','91011'=>'查不到昵称修改审核单信息','91012'=>'其它错误','91040'=>'获取ticket的类型无效','301002'=>'无权限操作指定的应用','301005'=>'不允许删除创建者','301012'=>'参数 position 不合法','301013'=>'参数 telephone 不合法','301014'=>'参数 english_name 不合法','301015'=>'参数 mediaid 不合法','301016'=>'上传语音文件不符合系统要求','301017'=>'上传语音文件仅支持AMR格式','301021'=>'参数 userid 无效','301022'=>'获取打卡数据失败','301023'=>'useridlist非法或超过限额','301024'=>'获取打卡记录时间间隔超限','301036'=>'不允许更新该用户的userid','302003'=>'批量导入任务的文件中userid有重复','302004'=>'组织架构不合法（1不是一棵树，2 多个一样的partyid，3 partyid空，4 partyid name 空，5 同一个父节点下有两个子节点 部门名字一样 可能是以上情况，请一一排查）','302005'=>'批量导入系统失败，请重新尝试导入','302006'=>'批量导入任务的文件中partyid有重复','302007'=>'批量导入任务的文件中，同一个部门下有两个子部门名字一样','600001'=>'不合法的sn','600002'=>'设备已注册','600003'=>'不合法的硬件activecode','600004'=>'该硬件尚未授权任何企业','600005'=>'硬件Secret无效','600007'=>'缺少硬件sn','600008'=>'缺少nonce参数','600009'=>'缺少timestamp参数','600010'=>'缺少signature参数','600011'=>'签名校验失败','600012'=>'长连接已经注册过设备','600013'=>'缺少activecode参数','600014'=>'设备未网络注册','600015'=>'缺少secret参数','600016'=>'设备未激活','600018'=>'无效的起始结束时间','600020'=>'设备未登录','600021'=>'设备sn已存在','600023'=>'时间戳已失效','600024'=>'固件大小超过5M','600025'=>'固件名为空或者超过20字节','600026'=>'固件信息不存在','600027'=>'非法的固件参数','600028'=>'固件版本已存在','600029'=>'非法的固件版本','600030'=>'缺少固件版本参数','600031'=>'硬件固件不允许升级','600032'=>'无法解析硬件二维码','2000002'=>'CorpId参数无效','9001001'=>'POST 数据参数不合法','9001002'=>'远端服务不可用','9001003'=>'Ticket 不合法','9001004'=>'获取摇周边用户信息失败','9001005'=>'获取商户信息失败','9001006'=>'获取 OpenID 失败','9001007'=>'上传文件缺失','9001008'=>'上传素材的文件类型不合法','9001009'=>'上传素材的文件尺寸不合法','9001010'=>'上传失败','9001020'=>'帐号不合法','9001021'=>'已有设备激活率低于 50% ，不能新增设备','9001022'=>'设备申请数不合法，必须为大于 0 的数字','9001023'=>'已存在审核中的设备 ID 申请','9001024'=>'一次查询设备 ID 数量不能超过 50','9001025'=>'设备 ID 不合法','9001026'=>'页面 ID 不合法','9001027'=>'页面参数不合法','9001028'=>'一次删除页面 ID 数量不能超过 10','9001029'=>'页面已应用在设备中，请先解除应用关系再删除','9001030'=>'一次查询页面 ID 数量不能超过 50','9001031'=>'时间区间不合法','9001032'=>'保存设备与页面的绑定关系参数错误','9001033'=>'门店 ID 不合法','9001034'=>'设备备注信息过长','9001035'=>'设备申请参数不合法','9001036'=>'查询起始值 begin 不合法',
            '89007'=>'小程序本月被关联的名额已用完','89008'=>'小程序为海外帐号，不允许关联','89009'=>'小程序关联达到上限','89010'=>'已经发送关联邀请','89011'=>'在附近中展示的小程序不能取消关联','89012'=>'门店、小店小程序不能取消关联','89013'=>'小程序被封禁','89015'=>'已经关联该小程序','89016'=>'公众号本月关联相同主体达到上限','89017'=>'公众号本月关联不同主体达到上限','89035'=>'已经从公众平台后台发起关联申请，处于小程序管理员确认中，无法从第三方重复发起关联申请','88000'=>'公众号没有开通留言功能','41030'=>'小程序页面尚未发布,无法生成','61051'=>'公众号主体类型不允许快速创建','61052'=>'公众号未认证','61053'=>'超过主体可注册数量上限','61054'=>'主体黑名单','61055'=>'超出公众号每月可快速创建限额','61056'=>'政府、媒体、其他组织必须复选微信认证','61057'=>'公众号仍有快速创建的账号在流程中','61058'=>'用户扫码凭证校验不通过','61028'=>'第三方平台未发布','61029'=>'第三方平台缺少必备权限集(帐号服务权限、程序帐号管理权限、小程序开发管理与数据分析权限)','61060'=>'转 uri 不合法','61061'=>'海外帐号不允许快速创建','89249'=>'该主体已有任务执行中，距上次任务24h后再试','89247'=>'内部错误','86004'=>'无效微信号','61070'=>'企业代码类型无效，请选择正确类型填写','89250'=>'未找到该任务','89251'=>'待法人人脸核身校验','89252'=>'法人&企业信息一致性校验中	','89253'=>'缺少参数','89254'=>'第三方权限集不全，补全权限集全网发布后生效','89255'=>'企业代码不正确','92000'=>'该经营资质已添加，请勿重复添加','92002'=>'附近地点添加数量达到上线，无法继续添加','92003'=>'地点已被其它小程序占用','92004'=>'附近功能被封禁','92005'=>'地点正在审核中','92006'=>'地点正在展示小程序','92007'=>'地点审核失败','92008'=>'程序未展示在该地点','93009'=>'小程序未上架或不可见','93010'=>'地点不存在','93011'=>'个人类型小程序不可用','93012'=>'非普通类型小程序（门店小程序、小店小程序等）不可用','93013'=>'从腾讯地图获取地址详细信息失败','93014'=>'同一资质证件号重复添加','61007'=>'无接口权限或您授权了多个平台,请前往公众平台登录小程序账号,在[设置-第三方设置]中取消所有授权,然后重新授权','1003'=>'商品id不存在','300001'=>'禁止创建/更新商品 或 禁止编辑&更新房间','300002'=>'名称长度不符合规则','300003'=>'价格输入不合规（如：现价比原价大、传入价格非数字等）','300004'=>'商品名称存在违规违法内容','300005'=>'商品图片存在违规违法内容','300006'=>'图片上传失败（如：mediaID过期）','300007'=>'线上小程序版本不存在该链接','300008：添加商品失败','300009：商品审核撤回失败','300010：商品审核状态不对（如：商品审核中）','300011：操作非法（API不允许操作非API创建的商品）','300012'=>'没有提审额度（每天500次提审额度）','300013'=>'提审失败','300014'=>'审核中，无法删除（非零代表失败）','300017'=>'商品未提审','300018'=>'商品图片尺寸过大','300021'=>'商品添加成功，审核失败','300022'=>'此房间号不存在','300023'=>'房间状态 拦截（当前房间状态不允许此操作）','300024'=>'商品不存在','300025'=>'商品审核未通过','300026'=>'房间商品数量已经满额','300027'=>'导入商品失败','300028'=>'房间名称违规','300029'=>'主播昵称违规','300030'=>'主播微信号不合法','300031'=>'直播间封面图不合规','300032'=>'直播间分享图违规','300033'=>'添加商品超过直播间上限','300034'=>'主播微信昵称长度不符合要求','300035'=>'主播微信号不存在','300036'=>'主播微信号未实名认证','300037'=>'购物直播频道封面图不合规','300038'=>'未在小程序管理后台配置客服','300039'=>'主播副号微信号不合法','300040'=>'名称含有非限定字符（含有特殊字符）','300041'=>'创建者微信号不合法','9410000'=>'直播间列表为空','9410001'=>'获取房间失败','9410002'=>'获取商品失败','9410003'=>'获取回放失败','400001'=>'微信号不合规','400002'=>'微信号需要实名认证，仅设置主播角色时可能出现','400003'=>'添加角色达到上限（管理员10个，运营者500个，主播500个）','400004'=>'重复添加角色','400005'=>'主播角色删除失败，该主播存在未开播的直播间',
        );
        if(is_array($rs)){
            return $err[$rs['errcode']] ? $err[$rs['errcode']] : $rs['errcode'].': '.$rs['errmsg'];
        }else{
            return $err[$rs] ? $err[$rs] : $rs;
        }
    }

    public function getAccessToken(){
        $wechatObj = self::$wechat_obj;
        if (!$access_token = $wechatObj->getAccessToken()) {
            return ['status' => 0, 'msg' => $wechatObj->getError()];
        }
        return ['status'=>1,'access_token'=>$access_token];
    }
}